﻿using System.Collections.Generic;
using UnityEngine;

namespace Core.RVO
{
    public class ObstacleSystem : Core.Component, IAwake
    {
        private readonly List<Obstacle> obstacles = new();

        public int Count => obstacles.Count;


        public Obstacle Get(int index)
        {
            if (index < 0 || index >= obstacles.Count) return null;

            return obstacles[index];
        }

        public void Awake()
        {

        }

        public override void Dispose()
        {
            if (IsDisposed) return;

            foreach (var obstacle in obstacles)
            {
                ReferencePool.Recycle(obstacle);
            }
            obstacles.Clear();

            base.Dispose();
        }

        public int Add(IList<Vector2> vertices)
        {
            if (vertices.Count < 2)
            {
                return -1;
            }

            int obstacleNo = obstacles.Count;

            for (int i = 0; i < vertices.Count; ++i)
            {
                Obstacle obstacle = ReferencePool.Acquire<Obstacle>();
                obstacle.Pos = vertices[i];

                if (i != 0)
                {
                    obstacle.Prev = obstacles[obstacles.Count - 1];
                    obstacle.Prev.Next = obstacle;
                }

                if (i == vertices.Count - 1)
                {
                    obstacle.Next = obstacles[obstacleNo];
                    obstacle.Next.Prev = obstacle;
                }

                obstacle.Dir = (vertices[(i == vertices.Count - 1 ? 0 : i + 1)] - vertices[i]).normalized;

                if (vertices.Count == 2)
                {
                    obstacle.Convex = true;
                }
                else
                {
                    obstacle.Convex = (RVOMath.LeftOf(vertices[(i == 0 ? vertices.Count - 1 : i - 1)], vertices[i], vertices[(i == vertices.Count - 1 ? 0 : i + 1)]) >= 0.0f);
                }

                obstacle.ID = obstacles.Count;
                obstacles.Add(obstacle);
            }

            return obstacleNo;
        }

        public void Add(Obstacle obstacle)
        {
            obstacles.Add(obstacle);
        }
    }
}
